<?php

namespace app\common\utils\http;

use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\RequestOptions as RO;

class HttpClientBuilder
{
    private ?string $name           = null;
    private array $config         = [];
    private int $timeout        = 60;

    private function __construct()
    {
    }

    /**
     * 名字
     *
     * @param string $name
     *
     * @return HttpClientBuilder
     */
    public static function newBuilder(string $name): HttpClientBuilder
    {
        $builder       = new self();
        $builder->name = $name;

        return $builder;
    }

    /**
     * GuzzleHttp config
     *
     * @param array $config
     *
     * @return HttpClientBuilder
     */
    public function config(array $config): HttpClientBuilder
    {
        $this->config = $config;

        return $this;
    }

    /**
     * 超时(秒), 优先使用config中设置
     *
     * @param int $timeout
     *
     * @return $this
     */
    public function timeout(int $timeout): HttpClientBuilder
    {
        $this->timeout = $timeout;

        return $this;
    }

    /**
     * 创建 GuzzleHttp
     *
     * @return HttpClient
     */
    public function create(): HttpClient
    {
        // 默认发送 gzip 请求头
        $default_options = [
            RO::HTTP_ERRORS     => true,
            RO::DECODE_CONTENT  => 'gzip',
            RO::ALLOW_REDIRECTS => false,
            RO::SYNCHRONOUS     => true,
            RO::CONNECT_TIMEOUT => 10,
            RO::READ_TIMEOUT    => $this->timeout,
            RO::TIMEOUT         => $this->timeout,
            // 'curl' => [
            //     CURLOPT_TCP_KEEPALIVE => 60,
            // ],
        ];


        $config = array_merge($default_options, $this->config);

        $stack = HandlerStack::create();

        $config['handler'] = $stack;

        $client       = new HttpClient($config);
        $client->name = $this->name;

        return $client;
    }


    /**
     * 构建HttpClient（基于GuzzleHttp）
     *
     * @param string $name   对方系统名称
     * @param array  $config 设置，参考 \GuzzleHttp\Client(array $config = [])  https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html
     *
     * @return HttpClient
     */
    public static function build(string $name, array $config = []): HttpClient
    {
        return self::newBuilder($name)->config($config)->create();
    }

}